// Contient toutes les spécifications de classes nécessaires
// pour représenter l'arbre abstrait
#ifndef ARBRE_H_
#define ARBRE_H_

#include <vector>
#include <iostream>
#include <iomanip>

#include "Symbole.h"

using namespace std;

// classe abstraite dont dériveront toutes les classes servant à représenter l'arbre abstrait
class Noeud
{
    public:
        virtual int  getValeur() = 0 ; // méthode pure (non implémentée) qui rend la classe abstraite
        virtual void afficher(unsigned short indentation = 0)
        {
            cout << setw(4 * indentation) << " ";       // pour afficher un noeud avec un décalage (indentation) proportionnel à son niveau dans l'arbre
        }
        virtual ~Noeud() {}
};

// classe pour représenter un noeud "sequence d'instruction" qui a autant de fils que d'instructions dans la séquence
class NoeudSeqInst : public Noeud
{

    public:
        NoeudSeqInst();   // construit une séquence d'instruction vide
        int getValeur(); // évalue chaque instruction de la séquence
        void afficher(unsigned short indentation = 0);    // affiche la séquence d'instructions
        void ajouteInstruction(Noeud* instruction);    // ajoute une instruction à la séquence
        ~NoeudSeqInst() {} // à cause du destructeur virtuel de la classe Noeud

    private:
        vector<Noeud *> m_tabInst; // pour stocker les instructions de la séquence

};

// classe pour représenter un noeud "affectation" composé de 2 fils : la variable et l'expression qu'on lui affecte
class NoeudAffectation : public Noeud
{

    public:
        NoeudAffectation(Noeud* variable, Noeud* expression);    // construit une affectation
        ~NoeudAffectation() {} // à cause du destructeur virtuel de la classe Noeud
        int getValeur(); // évalue l'expression et affecte sa valeur à la variable
        void afficher(unsigned short indentation = 0);    // affiche l'affectation

    private:
        Noeud* m_variable;
        Noeud* m_expression;

};

// classe pour représenter un noeud "opération arithmétique" composé d'un opérateur (+-*/) et de 2 fils : l'opérande gauche et l'opérande droit
class NoeudOperateurBinaire : public Noeud
{

    public:
        NoeudOperateurBinaire(Symbole operateur, Noeud* operandeGauche, Noeud* operandeDroit);    // construit une opération binaire : operandeGauche operateur OperandeDroit
        ~NoeudOperateurBinaire() {} // à cause du destructeur virtuel de la classe Noeud
        int getValeur(); // évalue l'operande gauche, l'operande droit et applique l'opérateur
        void afficher(unsigned short indentation = 0);    // affiche l'opération

    private:
        Symbole m_operateur;
        Noeud*  m_operandeGauche;
        Noeud*  m_operandeDroit;

};

class NoeudInstSi : public Noeud
{
    public:
        NoeudInstSi(Noeud* expression);
        int getValeur();
        ~NoeudInstSi() {}
    private:
        Noeud* m_expression;
};
#endif /* ARBRE_H_ */
